package com.jpxx.netty.hello;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

 
//hello useMe
public class Server {  
	  
    private int port;  
      
    public Server(int port) {  
        this.port = port;  
    }  
    
    /***
     * NioEventLoopGroup 是用来处理I/O操作的多线程事件循环器，
     * Netty提供了许多不同的EventLoopGroup的实现用来处理不同传输协议。
     * 在这个例子中我们实现了一个服务端的应用，
     * 因此会有2个NioEventLoopGroup会被使用。
     * 第一个经常被叫做‘boss’，用来接收进来的连接。
     * 第二个经常被叫做‘worker’，用来处理已经被接收的连接，
     * 一旦‘boss’接收到连接，就会把连接信息注册到‘worker’上。
     * 如何知道多少个线程已经被使用，如何映射到已经创建的Channels上都需要依赖于EventLoopGroup的实现，
     * 并且可以通过构造函数来配置他们的关系。
     */
    public void start(){  
        EventLoopGroup boss = new NioEventLoopGroup();//1.一个用户服务器端接收客户端连接的
        EventLoopGroup worker = new NioEventLoopGroup();//进行网络通信（网络读写）
		try {
			ServerBootstrap b = new ServerBootstrap();// 2.创建辅助工具类，用于服务器通道一系列配置
			b.group(boss, worker)//绑定2个线程组
					.channel(NioServerSocketChannel.class)// 指定NIO模式，只需要把SocketChannel放到netty的channel中
					.option(ChannelOption.SO_BACKLOG, 1024)// 设置tcp缓冲区,客户端连接的大小限制，超出了TCP内核就拒绝
					.option(ChannelOption.SO_SNDBUF, 32 * 1024)// 设置发送缓冲大小
					.option(ChannelOption.SO_RCVBUF, 32 * 1024)// 这是接收缓冲大小
					.option(ChannelOption.SO_KEEPALIVE, true)// 保持连接
					.childHandler(new ChannelInitializer<SocketChannel>() {
						@Override
						protected void initChannel(SocketChannel sc)
								throws Exception {
							//pipeline就是管道，类似于过滤器
							sc.pipeline().addLast(new ServerHandler()); // 3. 在这里配置具体接收数据方法的处理
							
						};
					});

			ChannelFuture cf1 = b.bind(port).sync(); // 4.进行绑定  sync异步阻塞
			System.out.println("服务器启动，监听" + port + "端口号");

			//Thread.slepp(Integer.MAX_VALUE);
			cf1.channel().closeFuture().sync();// 5等待关闭，销毁  优雅关机
		} catch (Exception e) {
			boss.shutdownGracefully();//关闭后，把实例化的2个线程组  关闭
			worker.shutdownGracefully();
		}
    }  
      
    public static void main(String[] args) throws Exception {  
        int port;  
        if (args.length > 0) {  
            port = Integer.parseInt(args[0]);  
        } else {  
            port = 2555;//这是端口号 
        }  
        new Server(port).start();  
    }  
}  